package br.com.rotary.utilitario;

import br.com.rotary.modelo.Anexo;
import java.io.*;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import net.coobird.thumbnailator.name.Rename;

/**
 *
 * @author laverson
 */
public class ArquivoUtilitario {

    private static final String REAL_PATH_TMP = "/tmp/uploads/";
    private static final String REAL_PATH_OPT = "/opt/uploads/";
    private static final String THUMBNAIL = "thumbnail";

    public ArquivoUtilitario() {
    }

    /**
     *
     * Adiciona um anexo a lista de anexos do processo que está sendo adicionado
     * a lista de processos do protocolo
     *
     * @param event
     * @throws FileNotFoundException
     * @throws SQLException
     * @throws IOException
     */
    public Anexo adicionarArquivo(byte[] bytes, String fileName, String contentType) throws FileNotFoundException, SQLException, IOException {
        try {
            Anexo anexo = new Anexo();

            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
            String data = dateFormat.format(new Date());

            String nomeExibicao = fileName.replace("/", " ");
            String nomeReal = data + nomeExibicao;

            anexo.setNome(nomeReal);

            // Aqui cria o diretorio caso não exista
            File file = new File(REAL_PATH_TMP);
            file.mkdirs();

            byte[] arquivo = bytes;
            String caminho = REAL_PATH_TMP + nomeReal.trim();

            gravarArquivo(caminho, arquivo);
            criarMiniatura(caminho);

            anexo.setUrl(REAL_PATH_TMP);
            anexo.setArquivo(arquivo);
            anexo.setNomeExibicao(nomeExibicao);
            anexo.setTipo(contentType);

            return anexo;
        } catch (Exception ex) {
            Msg.messagemError("Erro ao Copiar Arquivo para Anexo");
            return null;
        }
    }

    /**
     *
     * Grava os anexos no diretório "/opt/uploads/"
     *
     * @param anexos, lista de anexos a serem gravados
     */
    public void gravarAnexos(List<Anexo> anexos) {
        for (Anexo a : anexos) {
            if (a.getId() == null) {
                gravarAnexo(a);
            }
        }
    }

    /**
     *
     * Grava o 'arquivo' no diretório informado pela 'url'
     *
     * @param caminho caminho onde o arquivo vai ser gravado
     * @param arquivo arquivo a ser gravado no 'caminho'
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void gravarArquivo(String caminho, byte[] arquivo) throws FileNotFoundException, IOException {
        // esse trecho grava o arquivo no diretório
        FileOutputStream fos = new FileOutputStream(caminho);
        fos.write(arquivo);
        fos.close();
    }

    /**
     *
     * Exclui o arquivo do diretório
     *
     * @param f Arquivo a ser removido
     * @return true, se removido com sucesso, false caso contrário
     * @throws FileNotFoundException
     */
    public boolean excluirArquivo(File f) throws FileNotFoundException {
        try {
            String[] s = f.getPath().split("/");
            String nomeImagem = s[3];
            String caminhoImagemMiniatura = "/" + s[1] + "/" + s[2] + "/";
            caminhoImagemMiniatura += THUMBNAIL + "." + nomeImagem;

            //converte o objeto file em array de bytes
            List<InputStream> inputStreams = new ArrayList<InputStream>();
            inputStreams.add(new FileInputStream(f.getPath()));
            inputStreams.add(new FileInputStream(caminhoImagemMiniatura));

            File fThumb = new File(caminhoImagemMiniatura);

            for (InputStream inputStream : inputStreams) {
                byte[] bytes = new byte[(int) f.length()];
                int offset = 0;
                int numRead = 0;
                while (offset < bytes.length && (numRead = inputStream.read(bytes, offset, bytes.length - offset)) >= 0) {
                    offset += numRead;
                }
                inputStream.close();
            }

            fThumb.delete();
            f.delete(); //Deleta o arquivo onde foi criado

            return true;

        } catch (IOException ex) {

            System.err.println(ex);
        }
        return false;
    }

    public void excluirArquivos(List<Anexo> anexos) {
        for (Anexo anexo : anexos) {
            try {
                excluirArquivo(new File(anexo.getUrl() + anexo.getNome()));
            } catch (FileNotFoundException ex) {
                Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     *
     * Cria uma miniatura da imagem existente no caminho informado
     *
     * @param caminhoImagem Caminho completo da imagem Ex: ../imagens/icon.png
     */
    public static void criarMiniatura(String caminhoImagem) {
        try {
            Thumbnails.of(new File(caminhoImagem)).crop(Positions.CENTER).size(60, 60).toFiles(Rename.PREFIX_DOT_THUMBNAIL);
        } catch (IOException ex) {
            System.err.println(ex);
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Seta os bytes dos arquivos como null
     *
     * @param anexos Lista dos anexos que serão modificados
     * @return anexos com os bytes removidos
     */
    public List<Anexo> removerBytes(List<Anexo> anexos) {
        for (Anexo anexo : anexos) {
            if (anexo.getId() == null) {
                removerBytes(anexo);
            }
        }

        return anexos;
    }

    public void removerBytes(Anexo anexo) {
        anexo.setArquivo(null);
    }

    public void gravarAnexo(Anexo a) {
        String oldPath = a.getUrl().concat(a.getNome());

        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
            String data = dateFormat.format(new Date());

            String nomeArquivo = Caracter.removeCaracterIgnoraPonto(a.getNome());
            nomeArquivo = Caracter.removerAcentos(nomeArquivo);
            nomeArquivo = Caracter.substituirEspacos(nomeArquivo);

            a.setNome(data + nomeArquivo);
            a.setUrl(REAL_PATH_OPT);

            gravarArquivo(a.getUrl() + a.getNome(), a.getArquivo());
            criarMiniatura(a.getUrl().concat(a.getNome()));

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            excluirArquivo(new File(oldPath));
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     *
     * Grava os anexos no diretório "/opt/uploads/"
     *
     * @param anexos, lista de anexos a serem gravados
     */
    public Anexo gravarAnexos(Anexo anexo) {
        if (anexo.getId() != null) {
            try {
                SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
                String data = dateFormat.format(new Date());

                anexo.setNomeExibicao(anexo.getNome());

                String nomeArquivo = Caracter.removecaracter(anexo.getNome());
                nomeArquivo = Caracter.removerAcentos(nomeArquivo);
                nomeArquivo = Caracter.substituirEspacos(nomeArquivo);

                anexo.setNome(anexo.getId() + "-" + data + nomeArquivo + tipoAnexo(anexo));
                anexo.setUrl(REAL_PATH_OPT);

                File uploads = new File(anexo.getUrl());

                if (!uploads.exists()) {
                    uploads.setReadable(true);
                    uploads.setWritable(true);
                    uploads.mkdir();
                }

                if (anexo.getArquivo() != null) {
                    gravarArquivo(anexo.getUrl() + anexo.getNome(), anexo.getArquivo());
                }

                criarMiniatura(anexo.getUrl().concat(anexo.getNome()));
            } catch (Exception ex) {
                System.err.println(ex);
            }
        }

        return anexo;
    }

    /**
     * Retorna a extensão do arquivo de acordo com o tipo
     *
     * @param anexo
     * @return
     */
    public String tipoAnexo(Anexo anexo) {
        if (anexo.getTipo().equals(".jpg") || anexo.getTipo().equals("image/jpeg")) {
            return ".jpg";
        }

        if (anexo.getTipo().equals("image/png")) {
            return ".png";
        }

        if (anexo.getTipo().equals("application/pdf")) {
            return ".pdf";
        }

        return "";
    }
}
